"""
Redis异步工具类
提供Redis的异步操作和分布式锁功能
"""

import json
import logging
from typing import Any, Optional

import redis.asyncio as aioredis
from pydantic import BaseModel

from app.utils.json_encoder import CustomEncoder

logger = logging.getLogger(__name__)


class RedisUtils:
    """Redis异步工具类"""

    def __init__(self, redis_client: aioredis.Redis):
        """初始化RedisUtils实例

        Args:
            redis_client: Redis客户端实例
        """
        self.redis_client = redis_client

    async def get_redis(self) -> aioredis.Redis:
        """获取Redis连接实例"""
        return self.redis_client

    # 基本操作
    async def set(self, key: str, value: Any, ex: Optional[int] = None) -> bool:
        """设置键值对"""
        return await self.redis_client.set(key, value, ex=ex)

    async def get(self, key: str) -> Optional[Any]:
        """获取键值"""
        return await self.redis_client.get(key)

    async def delete(self, *keys: str) -> int:
        """删除键"""
        return await self.redis_client.delete(*keys)

    async def exists(self, key: str) -> bool:
        """检查键是否存在"""
        return await self.redis_client.exists(key) == 1

    async def expire(self, key: str, time: int) -> bool:
        """设置过期时间"""
        return await self.redis_client.expire(key, time)

    async def ttl(self, key: str) -> int:
        """获取剩余过期时间"""
        return await self.redis_client.ttl(key)

    async def set_model(self, key: str, model: BaseModel, ex: int = None):
        """将 Pydantic 模型序列化后存储到 Redis"""
        await self.set(key, model.model_dump_json(), ex=ex)

    async def get_model(self, key: str, model_class: type[BaseModel]) -> Optional[BaseModel]:
        """从 Redis 中读取数据并反序列化为指定的 Pydantic 模型"""
        data = await self.get(key)
        if data:
            return model_class.model_validate_json(data)
        return None

    async def set_json(self, key: str, obj: Any, ex: int = None):
        """存储任意对象（自动序列化为 JSON）"""
        await self.set(key, json.dumps(obj, cls=CustomEncoder), ex=ex)

    async def get_json(self, key: str) -> Optional[Any]:
        """读取 JSON 数据并反序列化为 Python 对象"""
        data = await self.get(key)
        if data:
            return json.loads(data)
        return None
